use std::{net::SocketAddr, sync::Arc};

use http::{HeaderMap, HeaderName, HeaderValue, StatusCode};
use tokio::{
    io::{self, AsyncBufReadExt, AsyncWriteExt, BufReader},
    net::{TcpListener, TcpStream},
    sync::Mutex,
};

use crate::net::request::ServiceRequest;

use super::{
    request::{Body, Request},
    response::Response,
    route::Route,
    Method, Protocol,
};

pub type ResultResp = anyhow::Result<Response>;

pub struct Server {
    listener: TcpListener,
    pub port: u16,
    handles: Vec<Route>,
}

fn parse_header(header_str: &str) -> HeaderMap {
    let lines = header_str.lines();
    let mut map = HeaderMap::new();
    for line in lines {
        if let Some((key, value)) = line.split_once(':') {
            let value = if &value[..1] == " " {
                &value[1..]
            } else {
                value
            };
            map.insert(
                HeaderName::from_bytes(key.as_bytes()).unwrap(),
                HeaderValue::from_str(value).unwrap(),
            );
        }
    }
    map
}

async fn decoder(stream: TcpStream, server_port: u16, handles: Arc<Vec<Route>>) -> io::Result<()> {
    log::debug!("连接进入....");
    // let mut index = 0;
    let stream = Arc::new(Mutex::new(stream));
    'out: loop {
        let mut stream_guard = stream.lock().await;
        let mut reader = BufReader::new(&mut *stream_guard);
        let mut initial_line = String::new();
        let amt = match reader.read_line(&mut initial_line).await {
            Ok(amt) => amt,
            Err(err) => {
                log::error!("read_line error = {:?}", err);
                break;
            }
        };
        if amt == 0 {
            break;
        }
        let methods: Vec<&str> = initial_line.split(' ').collect();
        log::debug!("methods = {:?}", methods);
        if methods.len() != 3 {
            continue;
        }
        let method = match methods[0] {
            "GET" => Method::Get,
            "POST" => Method::Post,
            "PUT" => Method::Put,
            "SETUP" => Method::Setup,
            "GET_PARAMETER" => Method::GetParameter,
            "SET_PARAMETER" => Method::SetParameter,
            "TEARDOWN" => Method::Teardown,
            "RECORD" => Method::Record,
            _ => Method::Unknown,
        };
        let protocol = match methods[2] {
            "RTSP/1.0\r\n" => Protocol::Rtsp1_0,
            "HTTP/1.1\r\n" => Protocol::Http1_1,
            _ => Protocol::Unknown,
        };
        let uri = methods[1];
        let mut header_line = String::new();
        while reader.read_line(&mut header_line).await? > 2 {}
        let headers = parse_header(&header_line);
        let content_length: usize = headers
            .get("content-length")
            .map(|v| v.to_str().unwrap_or("0").parse().unwrap_or(0))
            .unwrap_or(0);

        let buf = reader.buffer().to_vec();
        drop(reader);
        drop(stream_guard);
        let body = Body::new(content_length, stream.clone(), buf);
        let request = Request::new(method, protocol, uri, headers, server_port);
        for handle in handles.iter() {
            if handle.check(&request) {
                let result = handle
                    .f
                    .new_service(ServiceRequest {
                        req: request,
                        body: Some(body),
                    })
                    .await;
                match result {
                    Ok(resp) => {
                        if resp.status() == StatusCode::INTERNAL_SERVER_ERROR {
                            break 'out;
                        }
                        let resp_bytes = resp.into_bytes();
                        let mut stream = stream.lock().await;
                        stream.write_all(&resp_bytes).await?;
                        // log::info!("resp = \n{}", String::from_utf8_lossy(&resp_bytes));
                        stream.flush().await?;
                    }
                    Err(err) => {
                        log::error!("{err:?}");
                        break 'out;
                    }
                }
                continue 'out;
            }
        }
        {
            let resp = Response::http_404();
            let mut stream = stream.lock().await;
            stream.write_all(&resp.into_bytes()).await?;
            stream.flush().await?;
        }
        // let resp = handles(request).await;
        // match resp {
        //     Ok(resp) => {
        //         if resp.status() == StatusCode::INTERNAL_SERVER_ERROR {
        //             break;
        //         }
        //         let resp_bytes = resp.into_bytes();
        //         stream.write_all(&resp_bytes).await?;
        //         // log::info!("resp = \n{}", String::from_utf8_lossy(&resp_bytes));
        //         stream.flush().await?;
        //     }
        //     Err(err) => {
        //         log::error!("{err:?}");
        //         break;
        //     }
        // }
    }
    log::debug!("连接断开....");
    Ok(())
}

impl Server {
    pub async fn bind_with_addr(addr: SocketAddr) -> Self {
        let port = addr.port();
        let listener = TcpListener::bind(addr).await.unwrap();
        Self {
            port,
            listener,
            handles: Vec::new(),
        }
    }

    pub async fn bind_default() -> Self {
        let listener = TcpListener::bind("0.0.0.0:0").await.unwrap();
        let port = listener.local_addr().unwrap().port();
        Self {
            port,
            listener,
            handles: Vec::new(),
        }
    }

    pub fn add_handles(&mut self, handles: Vec<Route>) {
        self.handles.extend(handles);
    }

    pub async fn run(self) -> io::Result<()> {
        let listener = self.listener;
        let handles = Arc::new(self.handles);
        loop {
            let (stream, _) = listener.accept().await?;
            tokio::task::spawn(decoder(stream, self.port, handles.clone()));
        }
    }
}
